﻿namespace Services.Implement;

/// <summary>
/// 用户服务
/// </summary>
public class UserBLL(ISqlSugarClient db, IFeatureBLL featureBLL) : BaseBLL<User>(db), IUserBLL
{
    private readonly ISqlSugarClient _db = db;
    private readonly IFeatureBLL _featureBLL = featureBLL;

    /// <summary>
    /// 用户列表分页
    /// </summary>
    /// <returns></returns>
    public async Task<List<UserVM>> QueryPageListAsync(UserQueryRM pageQuery, RefAsync<int> total)
    {
        var userList = await GetListAsync<User>(x => x.Id != 1);
        var roleList = await GetListAsync<Role>();
        var list = userList.Select(user => new UserVM
        {
            Id = user.Id,
            Userid = user.UserId,
            Account = user.Account,
            RoleId = user.RoleId,
            Roles = user.Roles,
            Name = user.Name,
            Type = user.Type,
            Gender = user.Gender,
            Avatar = user.Avatar,
            OrgCode = user.OrgCode,
            OrgName = user.OrgName,
            Enable = user.Enable,
            CreateTime = user.CreateTime
        }).ToList();
        foreach (var user in list)
        {
            var rolenameList = roleList.Where(r => user.Roles.Contains(r.Id)).Select(r => r.Name).ToList();
            user.RoleName = string.Join("、", rolenameList);
        }
        if (!string.IsNullOrWhiteSpace(pageQuery.SearchKey))
        {
            list = list.Where(x => x.Account.Contains(pageQuery.SearchKey) || x.Name.Contains(pageQuery.SearchKey)).ToList();
        }
        if (pageQuery.Type != null && pageQuery.Type != -1)
        {
            list = list.Where(x => x.Type == pageQuery.Type).ToList();
        }
        if (pageQuery.RoleIds != null && pageQuery.RoleIds.Any())
        {
            list = list.Where(x => pageQuery.RoleIds.Intersect(x.Roles).Count() > 0).ToList();
        }
        if (pageQuery.Enable != -1)
        {
            list = list.Where(x => x.Enable == pageQuery.Enable).ToList();
        }
        if (!string.IsNullOrWhiteSpace(pageQuery.OrgName))
        {
            list = list.Where(x => !string.IsNullOrWhiteSpace(x.OrgName) && x.OrgName.Contains(pageQuery.OrgName)).ToList();
        }
        total.Value = list.Count;

        #region 排序
        pageQuery.FieldName = !string.IsNullOrWhiteSpace(pageQuery.FieldName) ? pageQuery.FieldName.ToLower() : string.Empty;
        if (string.IsNullOrWhiteSpace(pageQuery.FieldName))
        {
            list = list.OrderByDescending(t => t.Id).ToList();
        }
        else
        {
            if (pageQuery.Desc)
            {
                if (pageQuery.FieldName == "type")
                {
                    list = list.OrderByDescending(t => t.Type).ToList();
                }
                else if (pageQuery.FieldName == "rolename")
                {
                    list = list.OrderByDescending(t => t.RoleName).ToList();
                }
                else if (pageQuery.FieldName == "gender")
                {
                    list = list.OrderByDescending(t => t.Gender).ToList();
                }
                else if (pageQuery.FieldName == "enable")
                {
                    list = list.OrderByDescending(t => t.Enable).ToList();
                }
                else if (pageQuery.FieldName == "orgname")
                {
                    list = list.OrderByDescending(t => t.OrgName).ToList();
                }
            }
            else
            {
                if (pageQuery.FieldName == "type")
                {
                    list = list.OrderBy(t => t.Type).ToList();
                }
                else if (pageQuery.FieldName == "rolename")
                {
                    list = list.OrderBy(t => t.RoleName).ToList();
                }
                else if (pageQuery.FieldName == "gender")
                {
                    list = list.OrderBy(t => t.Gender).ToList();
                }
                else if (pageQuery.FieldName == "enable")
                {
                    list = list.OrderBy(t => t.Enable).ToList();
                }
                else if (pageQuery.FieldName == "orgname")
                {
                    list = list.OrderBy(t => t.OrgName).ToList();
                }
            }
        }
        #endregion

        var pageList = list.Skip((pageQuery.PageIndex - 1) * pageQuery.PageSize).Take(pageQuery.PageSize).ToList();
        return pageList;
    }
    /// <summary>
    /// 查询用户通过账号
    /// </summary>
    /// <param name="account"></param>
    /// <returns></returns>
    public async Task<User> GetUserByAccountAsync(string account)
    {
        return await GetAsync(x => x.Account == account);
    }

    /// <summary>
    /// 新增用户
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    public async Task<ResultModel> AddUserAsync(User user)
    {
        var ret = new ResultModel();
        ret.data = await InsertAsync(user);
        return ret;
    }

    /// <summary>
    /// 编辑用户
    /// </summary>
    /// <param name="user"></param>
    /// <returns></returns>
    public async Task<ResultModel> UpdateUserAsync(User user)
    {
        var ret = new ResultModel();
        var existUser = await GetAsync(x => x.Id == user.Id);
        if (existUser == null || existUser.Id <= 0)
        {
            ret.code = -1;
            ret.msg = "未获取到用户！";
            return ret;
        }
        existUser.RoleId = user.RoleId;
        existUser.Roles = user.Roles;
        existUser.Enable = user.Enable;
        existUser.Name = user.Name;
        existUser.Type = user.Type;
        existUser.Gender = user.Gender;
        existUser.Avatar = user.Avatar;
        existUser.OrgCode = user.OrgCode;
        existUser.OrgName = user.OrgName;
        var res = await UpdateAsync(existUser);
        ret.data = res;
        ret.code = res ? 1 : -1;
        return ret;
    }

    /// <summary>
    /// 设置用户角色
    /// </summary>
    /// <param name="rm"></param>
    public async Task<ResultModel> SetUserRoleByIdsAsync(SetUserRoleByIdsRM rm)
    {
        var ret = new ResultModel();
        if (rm.Ids == null || !rm.Ids.Any())
        {
            ret.code = -1;
            ret.msg = "参数异常！";
            return ret;
        }
        var userList = await GetListAsync(x => rm.Ids.Contains(x.Id));
        if (userList == null || !userList.Any())
        {
            ret.code = -1;
            ret.msg = "未获取到用户！";
            return ret;
        }
        foreach (var user in userList)
        {
            user.Roles = rm.RoleIds;
            user.RoleId = rm.RoleIds.First();
        }
        var res = await UpdateAsync(userList);
        ret.data = res;
        ret.code = res ? 1 : -1;
        return ret;
    }

    /// <summary>
    /// 设置用户状态
    /// </summary>
    /// <param name="rm"></param>
    public async Task<ResultModel> SetUserEnableByIdsAsync(SetEnableRM rm)
    {
        var ret = new ResultModel();
        if (rm.Ids == null || !rm.Ids.Any())
        {
            ret.code = -1;
            ret.msg = "参数异常！";
            return ret;
        }
        var userList = await GetListAsync(x => rm.Ids.Contains(x.Id));
        if (userList == null || !userList.Any())
        {
            ret.code = -1;
            ret.msg = "未获取到用户！";
            return ret;
        }
        userList.ForEach(x => { x.Enable = rm.Enable; });
        var res = await UpdateAsync(userList);
        ret.data = res;
        ret.code = res ? 1 : -1;
        return ret;
    }

    /// <summary>
    /// 根据用户类型设置用户角色
    /// </summary>
    /// <param name="rm"></param>
    public async Task<ResultModel> SetUserRoleByUserTypeAsync(SetUserRoleByUserTypeRM rm)
    {
        var ret = new ResultModel();
        if (rm.UserType < 0 || !rm.RoleIds.Any())
        {
            ret.code = -1;
            ret.msg = "参数异常！";
            return ret;
        }
        var userList = await GetListAsync(x => x.Type == rm.UserType);
        if (userList == null || !userList.Any())
        {
            ret.code = -1;
            ret.msg = "未获取到用户！";
            return ret;
        }
        foreach (var user in userList)
        {
            user.Roles = rm.RoleIds;
            user.RoleId = rm.RoleIds.First();
        }
        var res = await UpdateAsync(userList);
        ret.data = res;
        ret.code = res ? 1 : -1;
        return ret;
    }

    #region 教师树
    /// <summary>
    /// 获取教师树
    /// </summary>
    /// <returns></returns>
    public async Task<BDS_Tree?> GetTeacherTree(TreeRM rm)
    {
        // 查询所有教师
        var teachers = await GetListAsync(x => x.Type == (int)UserTypeEnum.Teacher && !SqlFunc.JsonArrayAny(x.Roles, 1));
        if (rm.IsFilterAdminRole)
        {
            teachers = teachers.Where(x => !x.Roles.Contains(2)).ToList();
        }
        // 唯一标识
        int indexId = 5000;

        var userlist = new List<int>();
        if (rm.Roleid != 0)
        {
            var list = await GetListAsync(x => SqlFunc.JsonArrayAny(x.Roles, rm.Roleid));
            if (list != null)
            {
                userlist = list.Select(x => x.Id).ToList();
            }

        }
        if (!string.IsNullOrWhiteSpace(rm.SearchWords))
        {
            var sw = Regex.Replace(rm.SearchWords.TrimStart().TrimEnd(), @"\s+", " ");
            var swList = sw.Split(' ').ToList();
            teachers = teachers.Where(x => swList.Any(y => x.Name.Contains(y) || x.Account.Contains(y))).ToList();
        }
        if (teachers == null || !teachers.Any())
        {
            return null;
        }
        // 获取组织树
        var orgTree = await BDSData.GetOrgTreeAsync();
        foreach (var child in orgTree.nodes)
        {
            AddTeacherToOrgTree(child, teachers, userlist, ref indexId);
        }

        var teacherInOrg = teachers.Where(t => t.OrgCode == orgTree.code).ToList();

        foreach (var item in teacherInOrg)
        {
            indexId += 1;
            var tree = new BDS_Tree
            {
                indexid = indexId,
                id = item.Id,
                nodetype = 3,
                text = item.Name,
                code = item.Account,
                nodes = null
            };
            orgTree.nodes.Add(tree);
        }
        if (!string.IsNullOrWhiteSpace(rm.SearchWords))
        {
            PruneTreeFromInnerToOuter(orgTree, 3);
        }
        return orgTree;
    }

    /// <summary>
    /// 把用户添加到组织树
    /// </summary>
    /// <param name="orgTree"></param>
    /// <param name="teachers"></param>
    private void AddTeacherToOrgTree(BDS_Tree orgTree, List<User> teachers, List<int> userlist, ref int indexId)
    {
        if (orgTree.nodes != null && orgTree.nodes.Count > 0)
        {
            foreach (var child in orgTree.nodes)
            {
                var teacherInOrg = teachers.Where(t => t.OrgCode == child.code).ToList();
                if (teacherInOrg.Count == 0)
                {
                    return;
                }
                if (child.nodes == null)
                {
                    child.nodes = new List<BDS_Tree>();
                }
                foreach (var item in teacherInOrg)
                {
                    if (userlist.Any(x => x == item.Id))
                    {
                        continue;
                    }

                    indexId += 1;
                    var tree = new BDS_Tree
                    {
                        indexid = indexId,
                        id = item.Id,
                        nodetype = 3,
                        text = item.Name,
                        code = item.Account,
                        nodes = null
                    };
                    child.nodes.Add(tree);
                }
                AddTeacherToOrgTree(child, teachers, userlist, ref indexId);
            }
        }
        else
        {
            var teacherInOrg = teachers.Where(t => t.OrgCode == orgTree.code).ToList();
            if (teacherInOrg.Count == 0)
            {
                return;
            }

            orgTree.nodes = new List<BDS_Tree>();
            foreach (var item in teacherInOrg)
            {
                if (userlist.Any(x => x == item.Id))
                {
                    continue;
                }

                indexId += 1;
                var tree = new BDS_Tree
                {
                    indexid = indexId,
                    id = item.Id,
                    nodetype = 3,
                    text = item.Name,
                    code = item.Account,
                    nodes = null
                };
                orgTree.nodes.Add(tree);
            }
        }
    }

    /// <summary>
    /// 从内向外修剪树。
    /// </summary>
    /// <param name="node">当前节点。</param>
    private bool PruneTreeFromInnerToOuter(BDS_Tree node, int current_nodetype)
    {
        if (node == null || (node.nodetype != current_nodetype && node.nodes == null)) return false;

        if (node.nodetype != current_nodetype)
        {
            int index = 0;
            while (index < node.nodes.Count)
            {
                if (!PruneTreeFromInnerToOuter(node.nodes[index], current_nodetype))
                {
                    node.nodes.RemoveAt(index); // 移除不满足条件的子节点
                }
                else
                {
                    index++;
                }
            }
        }

        // 如果是专业节点且没有子节点，则返回false表示应该移除
        if (node.nodetype != current_nodetype && (node.nodes == null || node.nodes.Count == 0))
        {
            return false;
        }

        // 其他情况下保留该节点
        return true;
    }
    #endregion

    #region 学生树
    /// <summary>
    /// 学生树
    /// </summary>
    /// <returns></returns>
    public async Task<BDS_Tree?> GetStudentTree(TreeRM rm)
    {
        // 查询所有教师
        var studentList = await GetListAsync(x => x.Type == (int)UserTypeEnum.Student && !SqlFunc.JsonArrayAny(x.Roles, 1));
        if (rm.IsFilterAdminRole)
        {
            studentList = studentList.Where(x => !x.Roles.Contains(2)).ToList();
        }
        int indexId = 5000;
        var userlist = new List<int>();
        if (rm.Roleid != 0)
        {
            var list = await GetListAsync(x => SqlFunc.JsonArrayAny(x.Roles, rm.Roleid));
            if (list != null)
            {
                userlist = list.Select(x => x.Id).ToList();
            }
        }
        if (!string.IsNullOrWhiteSpace(rm.SearchWords))
        {
            var sw = Regex.Replace(rm.SearchWords.TrimStart().TrimEnd(), @"\s+", " ");
            var swList = sw.Split(' ').ToList();
            studentList = studentList.Where(x => swList.Any(y => x.Name.Contains(y) || x.Account.Contains(y))).ToList();
        }
        if (studentList == null || !studentList.Any())
        {
            return null;
        }

        var studentClassTree = await BDSData.GetStudentClassTreeAsync();
        foreach (var child in studentClassTree.nodes)
        {
            AddStudentTree(child, studentList, userlist, ref indexId);
        }
        if (!string.IsNullOrWhiteSpace(rm.SearchWords))
        {
            PruneTreeFromInnerToOuter(studentClassTree, 4);
        }
        return studentClassTree;
    }

    /// <summary>
    /// 学生添加到班级树
    /// </summary>
    /// <param name="studentClassTree"></param>
    /// <param name="students"></param>
    /// <param name="indexId"></param>
    private void AddStudentTree(BDS_Tree studentClassTree, List<User> students, List<int> userlist, ref int indexId)
    {
        if (studentClassTree.nodes != null && studentClassTree.nodes.Count > 0)
        {
            foreach (var child in studentClassTree.nodes)
            {
                AddStudentTree(child, students, userlist, ref indexId);
            }
        }

        if (studentClassTree.nodetype == 2)
        {
            var studentInClass = students.Where(t => t.OrgCode == studentClassTree.code).ToList();
            if (studentInClass.Count == 0)
            {
                return;
            }

            studentClassTree.nodes = new List<BDS_Tree>();
            foreach (var item in studentInClass)
            {
                if (userlist.Any(x => x == item.Id))
                {
                    continue;
                }

                indexId += 1;
                var tree = new BDS_Tree
                {
                    indexid = indexId,
                    id = item.Id,
                    nodetype = 4,
                    text = item.Name,
                    code = item.Account,
                    nodes = null
                };
                studentClassTree.nodes.Add(tree);
            }
        }
    }

    /// <summary>
    /// 获取其他人员列表
    /// </summary>
    /// <returns></returns>
    public async Task<List<User>> GetOtherList(TreeRM rm)
    {
        // 查询所有其他人员
        var otherList = await GetListAsync(x => x.Type == 0 && !SqlFunc.JsonArrayAny(x.Roles, 1));
        if (rm.IsFilterAdminRole)
        {
            otherList = otherList.Where(x => !x.Roles.Contains(2)).ToList();
        }
        if (!string.IsNullOrWhiteSpace(rm.SearchWords))
        {
            var sw = Regex.Replace(rm.SearchWords.TrimStart().TrimEnd(), @"\s+", " ");
            var swList = sw.Split(' ').ToList();
            otherList = otherList.Where(x => swList.Any(y => x.Name.Contains(y) || x.Account.Contains(y))).ToList();
        }
        return otherList;
    }
    #endregion

    /// <summary>
    /// 编辑用户
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    public async Task<ResultModel> UpdateUserRoleAsync(UpdateUserRoleInput input)
    {
        var ret = new ResultModel();
        var existUser = await GetAsync(x => x.Id == input.UserId);
        if (existUser == null || existUser.Id <= 0)
        {
            ret.code = -1;
            ret.msg = "未获取到用户！";
            return ret;
        }

        existUser.RoleId = input.RoleId;
        var res = await UpdateAsync(existUser);
        CacheHelper.Remove($"loginrole_{existUser.Account}");
        CacheHelper.Set($"loginrole_{existUser.Account}", existUser.RoleId, TimeSpan.FromHours(1));
        ret.data = await GetFeatureListByRoleIdAsync(input.RoleId);
        ret.code = res ? 1 : -1;
        return ret;
    }
    /// <summary>
    /// 根据角色Id获取功能权限列表
    /// </summary>
    /// <param name="roleId"></param>
    /// <returns></returns>
    private async Task<List<Feature>> GetFeatureListByRoleIdAsync(int roleId)
    {
        List<int>? featureIds = new List<int>();
        if (roleId != 1)
        {
            var role = await _db.Queryable<Role>().FirstAsync(x => x.Id == roleId);
            if (role != null && role.Features != null && role.Features.Any())
            {
                featureIds = role.Features;
            }
        }
        else
        {
            featureIds = (await _featureBLL.GetListAsync()).Select(f => f.Id).ToList();
        }
        if (featureIds == null || !featureIds.Any())
        {
            return new List<Feature>();
        }
        return await _featureBLL.GetListAsync(x => featureIds.Contains(x.Id));
    }
}
